package com.sunshine.hook;

import android.app.Activity;
import android.app.Application;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;

import com.sunshine.util.HookUtil;
import com.sunshine.util.IntentLogger;
import com.sunshine.util.LogUtil;

import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XposedHelpers;
import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam;

import static com.sunshine.constant.HookConstant.LTB_PACKAGE_NAME;
import static com.sunshine.constant.HookConstant.LTB_STUB_APP_NAME;
import static com.sunshine.constant.HookConstant.WECHAT_MAIN_ACTIVITY;
import static com.sunshine.constant.HookConstant.WECHAT_PACKAGE_NAME;
import static com.sunshine.util.ClassUtil.getClazz;
import static com.sunshine.util.HookUtil.getFieldValue;
import static com.sunshine.util.HookUtil.getVerName;
import static de.robv.android.xposed.XposedHelpers.findAndHookMethod;

/**
 * hook important message from other app
 *
 * @author Administrator
 */
public class HookManager implements IXposedHookLoadPackage {
    private Context ltbContext = null;
    private ChatHook mChatHook = null;
    private Context context = null;
    private WeChatPayHook mWeChatPayHook = null;

    private static boolean isWxHooked = false;

    @Override
    public void handleLoadPackage(LoadPackageParam param) {
        LogUtil.log("handleLoadPackage version : " + getVerName(ltbContext));
        if (null != param.appInfo && ((param.appInfo.flags & 129) == 0)) {
            printCallStack(param);
            ltbChatHook(param);
            weChatHook(param);
        }
    }

    private void ltbChatHook(final LoadPackageParam loadPackageParam) {
        if (LTB_PACKAGE_NAME.equals(loadPackageParam.packageName)) {
            final String str2 = loadPackageParam.processName;
            XposedHelpers.findAndHookMethod(LTB_STUB_APP_NAME, loadPackageParam.classLoader,
                    "onCreate", new XC_MethodHook() {
                        @Override
                        protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                            super.afterHookedMethod(param);
                            if (!LTB_PACKAGE_NAME.equals(str2)) {
                                return;
                            }
                            Application application = (Application) getFieldValue(param.thisObject, "ᵢˋ");
                            if (application == null) {
                                LogUtil.log("Application null");
                                return;
                            }
                            ltbContext = application.getBaseContext();
                            LogUtil.log("ltbChatHook version : " + getVerName(ltbContext));
                            if (mChatHook == null) {
                                mChatHook = new ChatHook(ltbContext);
                            }
                        }
                    });
        }
    }

    /**
     * 打印Intent参数和调用关系
     *
     * @param param
     */
    private void printCallStack(LoadPackageParam param) {
        ClassLoader classLoader = param.classLoader;
        Class test = getClazz("android.app.Activity", classLoader);
        if (test != null) {
            findAndHookMethod(test, "startActivityForResult", Intent.class, int.class, Bundle.class,
                    new XC_MethodHook() {
                        @Override
                        protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                            super.afterHookedMethod(param);
                            Intent intent = (Intent) param.args[0];
                            Bundle bundle = (Bundle) param.args[2];
                            IntentLogger.dump(intent);
                            IntentLogger.dumpExtras(bundle);
                            LogUtil.log("Activity startActivityForResult " + Log.getStackTraceString(new Throwable()));
                        }
                    });
        }
    }

    private void weChatHook(final LoadPackageParam loadPackageParam) {
        if (WECHAT_PACKAGE_NAME.equals(loadPackageParam.packageName)) {
            final String str2 = loadPackageParam.processName;
            XposedHelpers.findAndHookMethod(ContextWrapper.class, "attachBaseContext", Context.class, new XC_MethodHook() {
                @Override
                protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                    super.afterHookedMethod(param);
                    context = (Context) param.args[0];
                    if ((WECHAT_PACKAGE_NAME.equals(str2)) && (!isWxHooked)) {
                        isWxHooked = true;
                        mWeChatPayHook = new WeChatPayHook(context);
                        LogUtil.log("weChatHook version : " + HookUtil.getVerName(context));
                    }
                }
            });
            Class cls = getClazz(WECHAT_MAIN_ACTIVITY, loadPackageParam.classLoader);
            if (null != cls) {
                try {
                    XposedHelpers.findAndHookMethod(cls, "onCreate", Bundle.class, new XC_MethodHook() {
                        @Override
                        protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                            LogUtil.log("weChatHook LauncherUI onCreate");
                            super.afterHookedMethod(param);
                            Object object = param.thisObject;
                            Activity activity = (Activity) object;
                            if (mWeChatPayHook != null) {
                                mWeChatPayHook.initParam(loadPackageParam.classLoader, activity);
                            }
                        }
                    });
                    //mark 6.6.7 at ; 6.7.3 ao; 7.0.3 aI
                    XposedHelpers.findAndHookMethod(cls, "aI", Intent.class, new XC_MethodHook() {
                        @Override
                        protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                            super.afterHookedMethod(param);
                            if (mWeChatPayHook != null) {
                                mWeChatPayHook.setWxAccountStatus(true);
                            }
                        }
                    });
                } catch (Throwable v0) {
                    LogUtil.log("weChatHook LauncherUI onCreate throwable reason " + v0.getMessage());
                }
            }
        }
    }
}
